#include"TcpClient.h"
#include"packDef.h"
#include<process.h>
#include"TcpClientMediator.h"
TcpClient::TcpClient(INetMediator* pMediator):m_isStop(false),m_sock(INVALID_SOCKET),m_hThreadHandle(nullptr)
{
	m_pMediator = pMediator;
}
TcpClient::~TcpClient()
{
	//关闭网络
	UnInitNet();
}
//初始化网络,加载库、创建套接字、连接服务器
bool TcpClient::InitNet()
{
	//1、加载库
	WORD wVersionRequested = { 0 };
	WSADATA wsaData = { 0 };
	int err = -1;

	/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);	//WSA windows socket api
	if (err != 0) {
		printf("WSAStartup failed with error: %d\n", err);
		return false;
	}


	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
		printf("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return false;
	}
	else
		printf("The Winsock 2.2 dll was found okay\n");


	//2、创建套接字
	m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == m_sock)
	{
		printf("socket error: %d\n", WSAGetLastError());
		WSACleanup();
		return false;
	}
	else
	{
		printf("socket succeded\n");
	}
	//3——链接服务器connect
	sockaddr_in serverAddr;
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.S_un.S_addr = inet_addr(_DEF_TCP_SERVER_IP);
	serverAddr.sin_port = htons(_DEF_TCP_PORT);


	err = connect(m_sock, (sockaddr*)&serverAddr, sizeof(serverAddr));
	if (err == SOCKET_ERROR)
	{
		printf("connect error: %d\n", WSAGetLastError());
		closesocket(m_sock);
		WSACleanup();
		return false;
	}
	else
	{
		printf("connect succeded\n");
	}

	//4---创建线程 收数据 因为收数据是阻塞的所以要创建线程
	m_hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &RecvThread, this, 0, NULL);
	//为什么用_beginthreadex函数，因为运行时库的函数会创建内存块，
	//使用_beginthreadex函数在结束线程时候会帮助我们自动回收这些运行时库创建的内存块

	return true;
}

unsigned int __stdcall TcpClient::RecvThread(void* lpvoid)
{
	TcpClient* pThis = (TcpClient*)lpvoid;
	pThis->RecvData();
	return 0;
}

//关闭网络
void TcpClient::UnInitNet()
{
	//1、退出线程
	m_isStop = true;
	if (WAIT_TIMEOUT == WaitForSingleObject(m_hThreadHandle, 100)) {
		TerminateProcess(m_hThreadHandle, -1);
	}
	CloseHandle(m_hThreadHandle);
	m_hThreadHandle = nullptr;
	//2、关闭socke
	if (m_sock && m_sock != INVALID_SOCKET) {
		closesocket(m_sock);
	}
	//3、卸载库
	WSACleanup();
}

//发送数据
bool TcpClient::SendData(long ISendIp, char* buf, int nLen)
{

	//1、参数校验
	if (!buf || nLen < 0) {
		return false;
	}
	
	//2、先发包大小
	if (send(m_sock, (char*)&nLen, sizeof(int), 0) <= 0) {
		return false;
	}
	//3、再发包内容
	if (send(m_sock, buf, nLen, 0) <= 0) {
		return false;
	}
	return true;
}

//接收数据
void TcpClient::RecvData()
{
	int nRecvNum = 0;
	int nPckSize = 0;
	int offset = 0;
	while (!m_isStop) {
		//接受包大小
		nRecvNum = recv(m_sock, (char*)&nPckSize, sizeof(int), 0);
		if (nPckSize > 0) {
			//再接收包内容
			char* buf = new char[nPckSize];
			while (nPckSize) {
				nRecvNum = recv(m_sock, buf + offset, nPckSize, 0);
				if (nRecvNum > 0) {
					offset += nRecvNum;
					nPckSize -= nRecvNum;
				}
			}
			//接收完一个完整的包，数据发送给中介者类，offset清零
			this->m_pMediator->DealData(m_sock, buf, offset);//这里应该是offset而不是nPckSize
			offset = 0;//一定要记得清零

		}
	}
}
